using System;
using System.Collections.Generic;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using PS.WebParts.Rollup.Core;

namespace PS.WebParts.Rollup.GridViewWebPart
{
    internal class DataAdapter
    {
        private Dictionary<Type, ColumnConstructor> TypeDecoder = new Dictionary<Type, ColumnConstructor>();
        private Dictionary<SPFieldType, ColumnConstructor> SPTypeDecoder = new Dictionary<SPFieldType, ColumnConstructor>();
        private ATabularDataSourceView aTabView;

        private delegate BoundField ColumnConstructor();

        #region Factory Methods

        static private BoundField CreateDefColumn()
        {
            return new TextColumn();
        }

        static private BoundField CreateNumberColumn()
        {
            return new NumberColumn();
        }

        static private BoundField CreateDateTimeColumn()
        {
            return new DateTimeColumn();
        }

        static private BoundField CreateBooleanColumn()
        {
            return new BooleanColumn();
        }

        static private BoundField CreateUserColumn()
        {
            return new UserColumn();
        }

        #endregion

        public DataAdapter(IDataSource dataSource)
        {
            TypeDecoder.Add(typeof(int), CreateNumberColumn);
            TypeDecoder.Add(typeof(bool), CreateBooleanColumn);
            TypeDecoder.Add(typeof(DateTime), CreateDateTimeColumn);

            SPTypeDecoder.Add(SPFieldType.Boolean, CreateBooleanColumn);
            SPTypeDecoder.Add(SPFieldType.Integer, CreateNumberColumn);
            SPTypeDecoder.Add(SPFieldType.DateTime, CreateDateTimeColumn);
            SPTypeDecoder.Add(SPFieldType.User, CreateUserColumn);

            DataSourceView view = dataSource.GetView(string.Empty);
            aTabView = (ATabularDataSourceView)view;
        }

        public IEnumerable<BoundField> GetColumns()
        {
            ARollupDataSourceView rollupView = aTabView as ARollupDataSourceView;
            if (rollupView != null)
            {
                DataColumnCollection tableColumns = rollupView.GetData().Columns;
                foreach (DataColumn column in tableColumns)
                {
                    if (!column.ColumnName.StartsWith("_"))
                    {
                        SPFieldType fType = SPFieldType.Invalid;
                        if (column.ExtendedProperties.ContainsKey(FieldInfo.ExtPropKey))
                        {
                            fType = (SPFieldType)column.ExtendedProperties[FieldInfo.ExtPropKey];
                        }
                        ColumnConstructor construct;
                        if (!SPTypeDecoder.TryGetValue(fType, out construct))
                        {
                            construct = CreateDefColumn;
                        }

                        BoundField field = construct();
                        field.DataField = column.ColumnName;
                        field.HeaderText = column.ColumnName;
                        yield return field;
                    }
                }
            }
            else
            {
                DataTable t = aTabView.GetSchema();
                foreach (DataColumn dC in t.Columns)
                {
                    if (!dC.ColumnName.StartsWith("_"))
                    {
                        ColumnConstructor construct;
                        if (!TypeDecoder.TryGetValue(dC.GetType(), out construct))
                        {
                            construct = CreateDefColumn;
                        }
                        BoundField field = construct();
                        field.DataField = dC.ColumnName;
                        field.HeaderText = dC.ColumnName;
                        yield return field;
                    }
                }
            }
        }

        public void FillColumn(DataControlFieldCollection Col)
        {
            foreach (BoundField field in GetColumns())
                Col.Add(field);
        }

        public void FillColumn(ColumnCollection Col)
        {
            foreach (BoundField field in GetColumns())
                Col.Columns.Add(field);
        }

        public DataTable GetData() 
        {
            return aTabView.GetData();
        }
        public DataTable GetSchema()
        {
            return aTabView.GetSchema();
        }
    }
}
